package com.sgzn.sgpay.service.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.enums.TradeMark;
import com.sgzn.sgpay.exception.SgpayException;
import com.sgzn.sgpay.model.request.SgsUpdateCreditRequest;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.persistence.dao.TUserAccountMapper;
import com.sgzn.sgpay.persistence.domain.TUserAccount;
import com.sgzn.sgpay.persistence.domain.TUserAccountExample;
import com.sgzn.sgpay.service.SgsUpdateCreditService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 更新用户积分服务实现类
 * @author huangsenguang
 */
@Slf4j
@Transactional
@Service
public class SgsUpdateCreditServiceImpl implements SgsUpdateCreditService {

    @Autowired
    private TUserAccountMapper tUserAccountMapper;

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<Boolean> updateCredit(SgsUpdateCreditRequest sgsUpdateCreditRequest) {
        SgsResultResponse sgsResultResponse = new SgsResultResponse();
        Boolean resultFalg = null;
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            log.info("update userAccount credit start!!!");
            resultFalg = handleUpdateCredit(sgsUpdateCreditRequest);
            sgsResultResponse.setErrorCode(SgsResponseCode.C200.getResponseCode());
            sgsResultResponse.setErrorMsg(SgsResponseCode.C200.getResponseDesc());
        } catch (SgpayException e) {
            log.error("更新积分 业务异常：", e);
            sgsResultResponse.setErrorCode(e.getCode());
            sgsResultResponse.setErrorMsg(e.getDesc());
        } catch (Exception e) {
            log.error("更新积分失败:", e);
            sgsResultResponse.setErrorCode(SgsResponseCode.C503.getResponseCode());
            sgsResultResponse.setErrorMsg(SgsResponseCode.C503.getResponseDesc());
        } finally {
            lock.unlock();   //释放锁
            sgsResultResponse.setResult(resultFalg);
        }
        return sgsResultResponse;

    }

    private Boolean handleUpdateCredit(SgsUpdateCreditRequest sgsUpdateCreditRequest) {
        TUserAccountExample tUserAccountExample = new TUserAccountExample();
        TUserAccountExample.Criteria tUserAccountExampleCriteria = tUserAccountExample.createCriteria();
        tUserAccountExampleCriteria.andUserIdEqualTo(sgsUpdateCreditRequest.getUserId());
        List<TUserAccount> tUserAccounts = this.tUserAccountMapper.selectByExample(tUserAccountExample);

        TUserAccount tUserAccount = null;
        Boolean resultFlag = null;
        if (CollectionUtils.isNotEmpty(tUserAccounts)) {
            log.info("存在有效用户!!!");
            tUserAccount = tUserAccounts.get(0);
            BigDecimal credit = new BigDecimal(sgsUpdateCreditRequest.getCredit());//消费积分
            BigDecimal accountCredit = tUserAccount.getAccountAmount();//历史积分
            BigDecimal targetCredit = accountCredit;

            if (TradeMark.INCREASE.getCode().equals(sgsUpdateCreditRequest.getTradeMark())) {//加
                targetCredit = accountCredit.add(credit);
            }
            if (TradeMark.DECREASE.getCode().equals(sgsUpdateCreditRequest.getTradeMark())) {//减
                if (credit.compareTo(accountCredit) > 0) {
                    throw new SgpayException(SgsResponseCode.C_BALANCE_NOT_ENOUGH.getResponseCode(),SgsResponseCode.C_BALANCE_NOT_ENOUGH.getResponseDesc());
                }
                targetCredit = accountCredit.subtract(credit);
            }
            tUserAccount.setAccountAmount(targetCredit);
            this.tUserAccountMapper.updateByPrimaryKeySelective(tUserAccount);
            resultFlag = true;
        }
        return resultFlag;
    }

    public static void main(String[] args){
        BigDecimal his = new BigDecimal(10.00);
        BigDecimal amount = new BigDecimal(0.01);
        BigDecimal target = his.add(amount);
        System.out.println(his + "| "+ target);
    }
}

